home *** CD-ROM | disk | FTP | other *** search
/ Freelog 125 / Freelog_MarsAvril2015_No125.iso / Musique / Quod Libet / quodlibet-3.3.0-installer.exe / bin / quodlibet / qltk / renamefiles.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2014-12-31  |  12KB  |  291 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.7)
  3.  
  4. import os
  5. import unicodedata
  6. from gi.repository import Gtk, Gdk
  7. from quodlibet import const
  8. from quodlibet import qltk
  9. from quodlibet import util
  10. from quodlibet.plugins import PluginManager
  11. from quodlibet.parse import FileFromPattern
  12. from quodlibet.qltk._editutils import FilterPluginBox, FilterCheckButton
  13. from quodlibet.qltk._editutils import EditingPluginHandler
  14. from quodlibet.qltk.views import TreeViewColumn
  15. from quodlibet.qltk.cbes import ComboBoxEntrySave
  16. from quodlibet.qltk.models import ObjectStore
  17. from quodlibet.qltk.wlw import WritingWindow
  18. from quodlibet.util import connect_obj
  19. from quodlibet.util.path import fsdecode, fsnative
  20. from quodlibet.util.path import strip_win32_incompat_from_path
  21.  
  22. class SpacesToUnderscores(FilterCheckButton):
  23.     _label = _('Replace spaces with _underscores')
  24.     _section = 'rename'
  25.     _key = 'spaces'
  26.     _order = 1
  27.     
  28.     def filter(self, original, filename):
  29.         return filename.replace(' ', '_')
  30.  
  31.  
  32.  
  33. class StripWindowsIncompat(FilterCheckButton):
  34.     _label = _('Strip _Windows-incompatible characters')
  35.     _section = 'rename'
  36.     _key = 'windows'
  37.     _order = 1.1
  38.     
  39.     def __init__(self):
  40.         super(StripWindowsIncompat, self).__init__()
  41.         if os.name == 'nt':
  42.             self.set_active(False)
  43.             self.set_sensitive(False)
  44.             self.set_no_show_all(True)
  45.  
  46.     
  47.     def filter(self, original, filename):
  48.         return strip_win32_incompat_from_path(filename)
  49.  
  50.  
  51.  
  52. class StripDiacriticals(FilterCheckButton):
  53.     _label = _('Strip _diacritical marks')
  54.     _section = 'rename'
  55.     _key = 'diacriticals'
  56.     _order = 1.2
  57.     
  58.     def filter(self, original, filename):
  59.         filename = fsdecode(filename)
  60.         return fsnative(filter((lambda s: not unicodedata.combining(s)), unicodedata.normalize('NFKD', filename)))
  61.  
  62.  
  63.  
  64. class StripNonASCII(FilterCheckButton):
  65.     _label = _('Strip non-_ASCII characters')
  66.     _section = 'rename'
  67.     _key = 'ascii'
  68.     _order = 1.3
  69.     
  70.     def filter(self, original, filename):
  71.         filename = fsdecode(filename)
  72.         return fsnative(u''.join(map((lambda s: if not s <= '~' or s:
  73. passu'_'), filename)))
  74.  
  75.  
  76.  
  77. class Lowercase(FilterCheckButton):
  78.     _label = _('Use only _lowercase characters')
  79.     _section = 'rename'
  80.     _key = 'lowercase'
  81.     _order = 1.4
  82.     
  83.     def filter(self, original, filename):
  84.         return filename.lower()
  85.  
  86.  
  87.  
  88. class RenameFilesPluginHandler(EditingPluginHandler):
  89.     from quodlibet.plugins.editing import RenameFilesPlugin
  90.     Kind = RenameFilesPlugin
  91.  
  92.  
  93. class Entry(object):
  94.     
  95.     def __init__(self, song):
  96.         self.song = song
  97.  
  98.     new_name = None
  99.     
  100.     def name(self):
  101.         return fsdecode(self.song('~basename'))
  102.  
  103.     name = property(name)
  104.  
  105.  
  106. class RenameFiles(Gtk.VBox):
  107.     title = _('Rename Files')
  108.     FILTERS = [
  109.         SpacesToUnderscores,
  110.         StripWindowsIncompat,
  111.         StripDiacriticals,
  112.         StripNonASCII,
  113.         Lowercase]
  114.     handler = RenameFilesPluginHandler()
  115.     
  116.     def init_plugins(cls):
  117.         PluginManager.instance.register_handler(cls.handler)
  118.  
  119.     init_plugins = classmethod(init_plugins)
  120.     
  121.     def __init__(self, parent, library):
  122.         super(RenameFiles, self).__init__(spacing = 6)
  123.         self.set_border_width(12)
  124.         hbox = Gtk.HBox(spacing = 6)
  125.         cbes_defaults = const.NBP_EXAMPLES.split('\n')
  126.         self.combo = ComboBoxEntrySave(const.NBP, cbes_defaults, title = _('Path Patterns'), edit_title = _('Edit saved patterns...'))
  127.         self.combo.show_all()
  128.         hbox.pack_start(self.combo, True, True, 0)
  129.         self.preview = qltk.Button(_('_Preview'), Gtk.STOCK_CONVERT)
  130.         self.preview.show()
  131.         hbox.pack_start(self.preview, False, True, 0)
  132.         self.pack_start(hbox, False, True, 0)
  133.         self.combo.get_child().connect('changed', self._changed)
  134.         model = ObjectStore()
  135.         self.view = Gtk.TreeView(model = model)
  136.         self.view.show()
  137.         sw = Gtk.ScrolledWindow()
  138.         sw.set_shadow_type(Gtk.ShadowType.IN)
  139.         sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
  140.         sw.add(self.view)
  141.         self.pack_start(sw, True, True, 0)
  142.         self.pack_start(Gtk.VBox(), False, True, 0)
  143.         filter_box = FilterPluginBox(self.handler, self.FILTERS)
  144.         filter_box.connect('preview', self._RenameFiles__filter_preview)
  145.         filter_box.connect('changed', self._RenameFiles__filter_changed)
  146.         self.filter_box = filter_box
  147.         self.pack_start(filter_box, False, True, 0)
  148.         self.save = Gtk.Button(stock = Gtk.STOCK_SAVE)
  149.         self.save.show()
  150.         bbox = Gtk.HButtonBox()
  151.         bbox.set_layout(Gtk.ButtonBoxStyle.END)
  152.         bbox.pack_start(self.save, True, True, 0)
  153.         self.pack_start(bbox, False, True, 0)
  154.         render = Gtk.CellRendererText()
  155.         column = TreeViewColumn(_('File'), render)
  156.         
  157.         def cell_data_file(column, cell, model, iter_, data):
  158.             entry = model.get_value(iter_)
  159.             cell.set_property('text', entry.name)
  160.  
  161.         column.set_cell_data_func(render, cell_data_file)
  162.         column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
  163.         self.view.append_column(column)
  164.         render = Gtk.CellRendererText()
  165.         render.set_property('editable', True)
  166.         column = TreeViewColumn(_('New Name'), render)
  167.         
  168.         def cell_data_new_name(column, cell, model, iter_, data):
  169.             entry = model.get_value(iter_)
  170.             if not entry.new_name:
  171.                 pass
  172.             cell.set_property('text', u'')
  173.  
  174.         column.set_cell_data_func(render, cell_data_new_name)
  175.         column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
  176.         self.view.append_column(column)
  177.         connect_obj(self.preview, 'clicked', self._RenameFiles__preview, None)
  178.         connect_obj(parent, 'changed', self.__class__._RenameFiles__preview, self)
  179.         connect_obj(self.save, 'clicked', self._RenameFiles__rename, library)
  180.         render.connect('edited', self._RenameFiles__row_edited)
  181.         for child in self.get_children():
  182.             child.show()
  183.         
  184.  
  185.     
  186.     def __filter_preview(self, *args):
  187.         Gtk.Button.clicked(self.preview)
  188.  
  189.     
  190.     def __filter_changed(self, *args):
  191.         self._changed(self.combo.get_child())
  192.  
  193.     
  194.     def _changed(self, entry):
  195.         self.save.set_sensitive(False)
  196.         self.preview.set_sensitive(bool(entry.get_text()))
  197.  
  198.     
  199.     def __row_edited(self, renderer, path, new):
  200.         model = self.view.get_model()
  201.         entry = model[path][0]
  202.         new = new.decode('utf-8')
  203.         if entry.new_name != new:
  204.             entry.new_name = new
  205.             self.preview.set_sensitive(True)
  206.             self.save.set_sensitive(True)
  207.  
  208.     
  209.     def __rename(self, library):
  210.         model = self.view.get_model()
  211.         win = WritingWindow(self, len(model))
  212.         win.show()
  213.         was_changed = set()
  214.         skip_all = False
  215.         self.view.freeze_child_notify()
  216.         for entry in model.itervalues():
  217.             song = entry.song
  218.             new_name = entry.new_name
  219.             old_name = entry.name
  220.             if new_name is None:
  221.                 continue
  222.             
  223.             try:
  224.                 library.rename(song, fsnative(new_name), changed = was_changed)
  225.             except Exception:
  226.                 util.print_exc()
  227.                 if skip_all:
  228.                     continue
  229.                 RESPONSE_SKIP_ALL = 1
  230.                 buttons = (_('Ignore _All Errors'), RESPONSE_SKIP_ALL, Gtk.STOCK_STOP, Gtk.ResponseType.CANCEL, _('_Continue'), Gtk.ResponseType.OK)
  231.                 msg = qltk.Message(Gtk.MessageType.ERROR, win, _('Unable to rename file'), _('Renaming <b>%s</b> to <b>%s</b> failed. Possibly the target file already exists, or you do not have permission to make the new file or remove the old one.') % (util.escape(old_name), util.escape(new_name)), buttons = Gtk.ButtonsType.NONE)
  232.                 msg.add_buttons(*buttons)
  233.                 msg.set_default_response(Gtk.ResponseType.OK)
  234.                 resp = msg.run()
  235.                 skip_all |= (resp == RESPONSE_SKIP_ALL)
  236.                 mods = Gdk.Display.get_default().get_pointer()[3]
  237.                 skip_all |= mods & Gdk.ModifierType.SHIFT_MASK
  238.                 library.reload(song, changed = was_changed)
  239.                 if resp != Gtk.ResponseType.OK and resp != RESPONSE_SKIP_ALL:
  240.                     break
  241.                 
  242.  
  243.             if win.step():
  244.                 break
  245.                 continue
  246.         self.view.thaw_child_notify()
  247.         win.destroy()
  248.         library.changed(was_changed)
  249.         self.save.set_sensitive(False)
  250.  
  251.     
  252.     def __preview(self, songs):
  253.         model = self.view.get_model()
  254.         if songs is None:
  255.             songs = [ e.song for e in model.itervalues() ]
  256.         pattern_text = self.combo.get_child().get_text().decode('utf-8')
  257.         
  258.         try:
  259.             pattern = FileFromPattern(pattern_text)
  260.         except ValueError:
  261.             qltk.ErrorMessage(self, _('Path is not absolute'), _('The pattern\n\t<b>%s</b>\ncontains / but does not start from root. To avoid misnamed folders, root your pattern by starting it with / or ~/.') % util.escape(pattern)).run()
  262.             return None
  263.  
  264.         if pattern:
  265.             self.combo.prepend_text(pattern_text)
  266.             self.combo.write(const.NBP)
  267.         orignames = [ song['~filename'] for song in songs ]
  268.         newnames = [ pattern.format(song) for song in songs ]
  269.         for f in self.filter_box.filters:
  270.             if f.active:
  271.                 newnames = f.filter_list(orignames, newnames)
  272.                 continue
  273.         model.clear()
  274.         for song, newname in zip(songs, newnames):
  275.             entry = Entry(song)
  276.             entry.new_name = fsdecode(newname)
  277.             model.append(row = [
  278.                 entry])
  279.         
  280.         self.preview.set_sensitive(False)
  281.         self.save.set_sensitive(bool(pattern_text))
  282.         for song in songs:
  283.             if not song.is_file:
  284.                 self.set_sensitive(False)
  285.                 break
  286.                 continue
  287.             self.set_sensitive(True)
  288.             return None
  289.  
  290.  
  291.